#include "Dictionnary_i.h"

list<Entity_i>Dictionnary_i::listEntity; 
int Dictionnary_i::index = 0;
char* Dictionnary_i::FILE_ENTRY = CORBA::string_dup("entries.dat");
char* Dictionnary_i::FILE_DEF = CORBA::string_dup("defs.dat");

Dictionnary_i::~Dictionnary_i(){}


CORBA::Boolean match(CategoryValue cat, const PropertyType& props){
	if((cat == NOM) && (props._d() == NOM))
		return true;
	else
	if((cat == VER) && (props._d() == VER))
		return true;
	else
	if((cat == ADJ) && (props._d() == ADJ))
		return true;
	else
		return false;
}


void Dictionnary_i::addEntity(const char* term, CategoryValue cat, const PropertyType& props, const char* def) throw (TermExisted, CategoryAndPropsNotMatch){
		
		//rechercher si le terme existe deja 
		list<Entity_i>::iterator it;
		CORBA::Boolean flag = false;
		int i=0;
		for (it = listEntity.begin(); it != listEntity.end(); it++){
		
			if(strcmp((*it).word.getTerm(),term) == 0){
			
				flag = true;
				listEntity.erase(it);
				break;
			}
			i++;
			}
	
		if(flag == true)
			throw TermExisted();
		if(match(cat,props) != true)
			throw CategoryAndPropsNotMatch();

		if(flag == false){
		
			Word_i *word = new Word_i(cat,props,CORBA::string_dup(term));	
			Entity_i *entity = new Entity_i(*word,CORBA::string_dup(def));
			listEntity.push_back(*entity);
		}
		
}

void Dictionnary_i::delEntity(const char* terms)throw (TermNotFound){
	
	list<Entity_i>::iterator it;
	CORBA::Boolean flag = false;
	int i=0;
	for (it = listEntity.begin(); it != listEntity.end(); it++){
		
		if(strcmp((*it).word.getTerm(),terms) == 0){
			
			flag = true;
			listEntity.erase(it);
			break;
		}
		i++;
	}
	
	if(flag == false)
		throw TermNotFound();
}

void Dictionnary_i::modifDefinition(const char* terms, const char* newdef) throw (TermNotFound){
	
	list<Entity_i>::iterator it;
	//int i =0;
	
	CORBA::Boolean flag = false;	
	
	for (it = listEntity.begin(); it != listEntity.end(); it++){
		
		if(strcmp((*it).word.getTerm(),terms) == 0){
			//free the previous allocated space 
			CORBA::string_free((*it).definition);
			(*it).definition = CORBA::string_dup(newdef);
			flag = true;
			break;				
		}
	}

	if(flag == false)
		throw TermNotFound();
}

Entity_ptr Dictionnary_i::findEntity(const char* term)throw (TermNotFound){
	list<Entity_i>::iterator it;
	int i =0;
	Entity_i *ent = NULL;	
	
	CORBA::Boolean flag = false;	
	
	for (it = listEntity.begin(); it != listEntity.end(); it++){
		
		if(strcmp((*it).word.getTerm(),term) == 0){
			index = i;
			flag = true;
			ent = new Entity_i((*it).word, (*it).definition);			
			return Dict::Entity::_duplicate((*ent)._this());
		}
		i++;
	}

	if(flag == false)
		throw TermNotFound();

	return ((*ent)._this());
}


::CORBA::Long Dictionnary_i::dictLength(){
	return (::CORBA::Long) listEntity.size();
}


::CORBA::Long Dictionnary_i::loadDict()throw (DicFileNotFound){

	//ifstream _entry (FILE_ENTRY);
	ifstream _entry ("entries.dat");
	ifstream _definition("defs.dat");
	//ifstream _definition(FILE_DEF);
	
	CORBA::Long value = 0;
	
	try{	

	if(!_entry.is_open() || !_definition.is_open())
		throw DicFileNotFound();	
	
	string entite;
	string definition;		

	int i;	
	
	
	listEntity.clear();
		
	char liste[5][256];
	//ce tableau a deux dimension permet de recuperer les valeurs d'une ligne dans le fichier d'entree
	
	char def_text[1000];
	
	while (getline(_entry,entite)){
		char * test;
		char * pch;
		i=0;	
		//test = (char*) malloc (sizeof(entite.length()+1));	
		
		test = CORBA::string_alloc(entite.length());	
		
		sprintf(test,"%s",entite.c_str());
		pch = strtok (test," [,.«<]>»");
		while (pch != NULL)
  		{	
    			//printf ("%s\n",pch);
			strcpy(liste[i],pch);
			i++;
    			pch = strtok (NULL, "[,.«<]>»");
  		}

		getline(_definition,definition);

		//char *def = (char*) malloc (sizeof(definition.length()+1));	
		
		char *def = CORBA::string_alloc(definition.length());
		char *wd;
		sprintf(def,"%s",definition.c_str());
		wd = strtok (def,",«»");
		while(wd != NULL)
		{
			strcpy(def_text,wd);
			wd = strtok(NULL,",«»");
		}
		//ajout du mot dans la liste
		PropertyType ptyTpe;
		CategoryValue catvalue;
		if(strcmp(liste[1],"NOM") == 0){
			catvalue = NOM;

			PropNom prnom;  
			if(strcmp(liste[3],"MASC") == 0)
				prnom.genre = MASC;
			else
				prnom.genre = FEM;

			//string *strin = new string(liste[4]);
			prnom.pluriel = CORBA::string_dup(liste[4]);
			//prnom.pluriel = *strin;
			
			ptyTpe.pNom(prnom);

			Word_i *word = new Word_i(catvalue,ptyTpe,CORBA::string_dup(liste[2]));	
			Entity_i *t = new Entity_i(*word,CORBA::string_dup(def_text));
			listEntity.push_back(*t);
		}
		else
           	if(strcmp(liste[1],"ADJ") == 0){
			catvalue = ADJ;
			//PropertyType pTpe;
			PropAdj	padj;

			padj.feminin = CORBA::string_dup(liste[3]);
			padj.pluriel = CORBA::string_dup(liste[4]);


			ptyTpe.pAdj(padj);
			
			Word_i *word = new Word_i(catvalue,ptyTpe,CORBA::string_dup(liste[2]));	
			Entity_i *t = new Entity_i(*word,CORBA::string_dup(def_text));
			listEntity.push_back(*t);
		}
		else{
			catvalue = VER;
			PropVer	pVerbe;
			if(strcmp(liste[3],"G1") == 0)
				pVerbe.groupe = G1;
			else 
			if(strcmp(liste[3],"G2") == 0)
				pVerbe.groupe = G2;
			else
				pVerbe.groupe = G3;
			//transitivite
			if(strcmp(liste[4],"TRANS") == 0)
				pVerbe.transitivite = TRANS;
			else
				pVerbe.transitivite = INTR;
			ptyTpe.pVer(pVerbe);
			
			Word_i *word = new Word_i(catvalue,ptyTpe,CORBA::string_dup(liste[2]));	
			Entity_i *t = new Entity_i(*word,CORBA::string_dup(def_text));
			listEntity.push_back(*t);
		}
	}
	_entry.close();
	_definition.close();
	//CORBA::Long value = listEntity.size();
	
	}catch(DicFileNotFound ex){
		cout<< "Unable to  open Dictionnary file " <<endl;
	}
	value = listEntity.size();
	return value; 
}


void Dictionnary_i::saveDict(){
	
	 if (listEntity.size() == 0) {
            return;
        }
	ofstream out_entity(FILE_ENTRY);
	ofstream out_definition(FILE_DEF);	
	
	int i = 1;
	list<Entity_i>::iterator it;
	
	for (it = listEntity.begin(); it != listEntity.end(); it++,i++){
		//converti l'entier en string
		std::stringstream convert;
		convert << i;
		string *sh = new string((*it).word.toFile());
		string *entite_lue = new string("[" + convert.str() + ",");
		string *tr = new string((*it).word.myTerm());  
		if((*it).word.myCategory() == NOM)
			entite_lue = new string(*entite_lue + "NOM" + ",«" + *tr + "»,");
		else
		if((*it).word.myCategory() == ADJ)
			entite_lue = new string (*entite_lue + "ADJ" + ",«" + *tr + "»,");
		else
		if((*it).word.myCategory() == VER)
			entite_lue = new string(*entite_lue + "VER" + ",«" + *tr + "»,");
		entite_lue = new string( *entite_lue + *sh + "]");
		
		out_entity << *entite_lue << endl;
	
		string *defin = new string((*it).definition);

		defin = new string(convert.str() + ",«" + *defin + "»"); 
		
		out_definition << *defin << endl;
	}

	out_definition.close();
	out_entity.close();
}

//index pointe sur l'element courant dans la liste


Entity_ptr Dictionnary_i::firstEntity()throw (DictEmpty){
	if (listEntity.size() == 0) {
            throw DictEmpty();
        }
	else{
		index = 0;
		return ((listEntity.front())._this());
	}		
}


Entity_ptr Dictionnary_i::lastEntity()throw (DictEmpty){
		
	if (listEntity.size() == 0) {
            throw DictEmpty();
        }
	else{
		index = listEntity.size() - 1;
		return ((listEntity.back())._this());
	}	
}


Entity_ptr Dictionnary_i::nextEntity()throw (DictEmpty){
	if (listEntity.size() == 0) {
            throw DictEmpty();
        }
	
	Entity_i *entity = NULL;	

	list<Entity_i>::iterator it;
	//est ce que l'index pointe sur le dernier element de la liste 

	if(index == (int)(listEntity.size() -1)){ //index pointe sur le dernier element du dictionnaire
		index = 0; 			// son suivant est le premier element de la liste
		return ((listEntity.front())._this());
	}
	else
	{
		int i =0;
		for (it = listEntity.begin(); it != listEntity.end(); it++){
			if(i == (index +1)){
				index += 1;
				entity = new Entity_i((*it).word,(*it).definition);
				//return (Entity_ptr)entity;	
				return Dict::Entity::_duplicate((*entity)._this());		
			}
			i++;
		}
		
	}
	return ((*entity)._this());
}


Entity_ptr Dictionnary_i::prevEntity()throw (DictEmpty){
	if (listEntity.size() == 0) {
            throw DictEmpty();
        }

	Entity_i *entity = NULL;	

	list<Entity_i>::iterator it;
	//est ce que l'index pointe sur le dernier element de la liste 
	if(index == 0){

		index = listEntity.size() - 1; 			
		return Dict::Entity::_duplicate((listEntity.back())._this());
	}		
	else
	{
		int i =0;
		for (it = listEntity.begin(); it != listEntity.end(); it++){
			if(i == (index - 1)){
				index = index - 1;
				//return (Entity_ptr)&(*it);
				entity = new Entity_i((*it).word,(*it).definition);
				return Dict::Entity::_duplicate((*entity)._this());			
			}
			i++;
		}
		
	}
	return ((*entity)._this());			
}



// comparison, not case sensitive.
CORBA::Boolean compare_nocase(Entity_i e1, Entity_i e2){
	unsigned int i=0;
  	while ( (i < strlen((e1.word).getTerm())) && (i<strlen((e2.word).getTerm())) )
  	{
    		if (tolower(((e1.word).getTerm())[i]) < (tolower(((e2.word).getTerm())[i]))) return true;
    		else if (tolower(((e1.word).getTerm())[i]) > (tolower(((e2.word).getTerm())[i]))) return false;
    		++i;
  	}
  if (strlen((e1.word).getTerm()) < strlen((e1.word).getTerm())) return true;
  else return false;
}

void Dictionnary_i::sortDict(::CORBA::Boolean dir){

	if( dir == true){
		//trie coissant
		//list<Entity_ptr>::iterator it;
		listEntity.sort(compare_nocase);
	}
	
	else{
		list<Entity_i> temp;
		listEntity.sort(compare_nocase);
		listEntity.reverse();
	}
}


